/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package processer;

import log.LogDef;
import main.BotManager;
import utils.Debug;

/**
 *
 * @author Administrator
 */
public class PhomPlayer extends Player {
    
    private static final int NUMBER_CARD_IN_HANDS = 10;
    private static final int FLUSH_SET = 1;
    private static final int PAIR_SET = 2;
    private static final int CHOOSE_PAIR = 1;
    private static final int CHOOSE_FLUSH = 2;
    private static final int CHOOSE_ALL = 3;
    private boolean isDepositCard;
    private int playerWinByUId;
    private int gameTurn;
    private int firstHaPhom;
    private int numberCardRemains;
    private int numberPlayersStart;
    private int numberPhoms;
    private int playerEatId;
    private int playerFightid;
    private int numberFlushs;
    private int numberEats;
    private int cardChooseIndex;
    private int cardEatedIndex0;
    private int cardEatedIndex1;
    private int cardEatedIndex2;
    private int cardEatedIndex3;
    private boolean isGetMoreCard;
    private boolean isEatCard;
    private boolean isHaPhom;
    //-------------------------------------------------------------------------
    private Card[] cardInHands;
    private Card[] cardEated1;
    private Card[] cardEated2;
    private Card[] cardEated3;
    private Card[] cardEated0;
    private Card cardCanbeEated;
    private Card[][] cardPhomSet;
    private Card[][] cardFighted;
    //-------------------------------------------------------------------------
    private int[][] phomSet;
    private int[] phomIndex;
    private int[] cardCheckIdArr;
    private int[][] pairSet;
    private int[] pairIndex;
    private int numberPairs;
    private int[][] flushSet;
    private int[] flushIndex;
    private int[] depositTargerArr;
    private int[] depositNumberArr;
    private int[] phomCardIndex;
    private int[] cardFightedIndex;
    private int[] depositPostion;
    private int[] depositCardArr;
    private int[] resultOrder;
    private boolean[] isBelongOfFlushSet;
    private boolean isFinishGame;
    private boolean[] flushSetChoosed;
    private boolean[] pairSetChoosed;
    private boolean[] isNotHavePhom;
    private int playeIdWin;
    private int countFnReceive;
    private boolean isStartFight;
    private boolean isBeginGame;
    private boolean isFightLastCard;
    private boolean isWaitFinish;
    private boolean isJoined;
    private int playerDenLang;
    private boolean isWaitingJoinResult;
    
    public PhomPlayer(RoBot parent, GameData gameData, BotManager manager) {
        super(parent, gameData, manager);
        initValue();
        initObject();
        if (gameData.cardInHandId != null && !isViewer) {
            setCardShare(gameData.cardInHandId);
        }
        if (isViewer) {
            initForViewer();
        }
    }
    
    private void initForViewer() {
        cardEated1 = new Card[3];
        cardEated2 = new Card[3];
        cardEated3 = new Card[3];
        cardEated0 = new Card[3];
    }
    
    private void setCardShare(int[] cardIds) {
        gameData.numberMatchPlays++;
        numberCardRemains = cardIds.length;
        Debug.d("number card remain :" + numberCardRemains);
        if (cardInHands == null) {
            cardInHands = new Card[NUMBER_CARD_IN_HANDS];
        }
        if (!isViewer) {
            //  sortCardPhom(cardIds, numberCardRemains);
            for (int i = 0; i < numberCardRemains; i++) {
                cardInHands[i] = new Card(cardIds[i]) {
                };
            }
        }
        numberPlayersStart = numberPlayers;
        
        if (!isViewer) {
            cardEated1 = new Card[3];
            cardEated2 = new Card[3];
            cardEated3 = new Card[3];
            cardEated0 = new Card[3];
            extractPhom();
            
        }
        
    }
    
    private void initValue() {
        isJoined = false;
        playerWinByUId = -1;
        playerDenLang = -1;
        isDepositCard = false;
        maxPlayer = gameData.getMaxPlayer();
        myViewId = gameData.getMyViewId();
        playerId = gameData.getPlayerId();
        gameTurn = gameData.getFirstTurn();
        isViewer = (myViewId < maxPlayer ? false : true);
        if (isViewer) {
            playerId = 0;
        }
        numberPlayers = gameData.getNumberPlayers();
        firstHaPhom = gameTurn;
        firtTurn = gameTurn;
        if (isViewer) {
            playerId = 0;
        }
        Debug.d(gameData.myName + ",isview :" + isViewer);
        gameData.setGameDisplay(this);
    }
    
    private void initObject() {
        initArr();
    }
    
    private void initArr() {
        isBelongOfFlushSet = new boolean[NUMBER_CARD_IN_HANDS];
        flushSetChoosed = new boolean[NUMBER_CARD_IN_HANDS + 5];
        pairSetChoosed = new boolean[NUMBER_CARD_IN_HANDS + 5];
//        phomIdArr = new int[NUMBER_CARD_IN_HANDS + 3];
        depositTargerArr = new int[5];
        depositNumberArr = new int[5];
        isNotHavePhom = new boolean[5];
        phomCardIndex = new int[5];
        cardFightedIndex = new int[5];
        cardFighted = new Card[5][5];
        cardPhomSet = new Card[5][10];
        depositPostion = new int[10];
        depositCardArr = new int[10];
        for (int i = 0; i < 5; i++) {
            cardFighted[i] = new Card[5];
            cardPhomSet[i] = new Card[10];
        }
        resultOrder = new int[4];
        
    }

//------------------------------------------------------------------------------
    private void printArr2(int[] arr, int index) {
        for (int i = 0; i < index; i++) {
            Debug.d("arr :" + arr[i]);
        }
    }
    
    private void sortIncreaseBySuit(int[] cardIds, int length) {
        for (int i = 0; i < length - 1; i++) {
            for (int j = i + 1; j < length; j++) {
                if (cardIds[i] / 13 > cardIds[j] / 13) {
                    int tg = cardIds[i];
                    cardIds[i] = cardIds[j];
                    cardIds[j] = tg;
                } else if (cardIds[i] / 13 == cardIds[j] / 13) {
                    if (cardIds[i] % 13 > cardIds[j] % 13) {
                        int tg = cardIds[i];
                        cardIds[i] = cardIds[j];
                        cardIds[j] = tg;
                    }
                }
            }
        }
    }
    
    private int findFlush(int[] cardIds, int length, int cardCheckEat, int[] resultId) {
        
        Debug.d("find flush ");
//        printArr2(cardIds, length);
        sortIncreaseBySuit(cardIds, length);
        for (int i = 0; i < length; i++) {
            if (i > 0) {
                if (cardCheckEat == cardIds[i] + 1
                        && cardCheckEat == cardIds[i - 1] + 2
                        && cardCheckEat / 13 == cardIds[i] / 13
                        && cardCheckEat / 13 == cardIds[i - 1] / 13) {
                    resultId[0] = cardIds[i - 1];
                    resultId[1] = cardIds[i];
                    resultId[2] = cardCheckEat;
                    return 3;
                }
            }
            if (i < length - 1) {
                if (cardCheckEat == cardIds[i] - 1
                        && cardCheckEat == cardIds[i + 1] - 2
                        && cardCheckEat / 13 == cardIds[i] / 13
                        && cardCheckEat / 13 == cardIds[i + 1] / 13) {
                    
                    resultId[0] = cardCheckEat;
                    resultId[1] = cardIds[i];
                    resultId[2] = cardIds[i + 1];
                    return 3;
                }
            }
            if (i > 0) {
                if (cardCheckEat == cardIds[i] - 1
                        && cardCheckEat == cardIds[i - 1] + 1
                        && cardCheckEat / 13 == cardIds[i] / 13
                        && cardCheckEat / 13 == cardIds[i - 1] / 13) {
                    resultId[0] = cardIds[i - 1];
                    resultId[1] = cardCheckEat;
                    resultId[2] = cardIds[i];
                    return 3;
                }
            }
            
        }
        return 0;
        
    }
    
    private int findPair(int[] cardIds, int length, int cardCheckEat, int[] resultId) {
        int count = 0;
        for (int i = 0; i < length; i++) {
            if (cardCheckEat % 13 == cardIds[i] % 13) {
                resultId[count] = cardIds[i];
                count++;
            }
        }
        resultId[count] = cardCheckEat;
        count++;
        sortCardIncrease(cardIds, length);
        return count;
    }
    
    private void extractPhom() {
//        Debug.d("extract phom ");
        //luu phom 
        phomSet = new int[3][5];
        phomIndex = new int[3];
        int checkIndex = 0;
        int startId = 0;
        if (cardCheckIdArr == null) {
            cardCheckIdArr = new int[NUMBER_CARD_IN_HANDS + 3];
        }
        //tim phom trong nhung quan ko trong bo da co
        for (int i = 0; i < numberCardRemains; i++) {
            Card card = cardInHands[i];
            if (card.isCardEated) {
                phomSet[card.eatId][card.phomId] = card.getCardId();
                phomIndex[card.eatId] = (phomIndex[card.eatId] > card.phomId + 1 ? phomIndex[card.eatId] : card.phomId + 1);
                startId = (card.eatId + 1 > startId ? card.eatId + 1 : startId);
            } else {
                cardCheckIdArr[checkIndex] = cardInHands[i].getCardId();
                checkIndex++;
            }
        }
        int saveId = startId;
        //chon ra bo ngang va bo doc
        numberPairs = extracPair(cardCheckIdArr, checkIndex);
        numberFlushs = extractFlush(cardCheckIdArr, checkIndex);
        //ko co phom nao
//        Debug.d("number pair :" + numberPairs);
//        Debug.d("number flush :" + numberFlushs);
//        Debug.d("startId :" + startId);
//        Debug.d("phom set:" + numberPhoms);
//        printArr(phomSet, phomIndex);
        if (numberFlushs > 0 && numberPairs == 0) {
            int index = 0;
            do {
                if (flushIndex[index] > 0) {
                    phomSet[startId] = flushSet[index];
                    phomIndex[startId] = flushIndex[index];
                    startId++;
                }
                index++;
            } while (index < 3);
        }
        
        
        if (numberPairs > 0 && numberFlushs == 0) {
            int index = 0;
            do {
                if (pairIndex[index] > 0) {
                    phomSet[startId] = pairSet[index];
                    phomIndex[startId] = pairIndex[index];
                    startId++;
                }
                index++;
            } while (index < 3);
        }
        
        if (numberFlushs > 0 && numberPairs > 0) {
            startId = choosePhom(startId);
        }
        //nhung quan nao ko thuoc phom ma thuoc vao bo san co
        if (saveId > 0) {
            markPhom();
            // danh dau nhung quan la phom
            int[] cardNotPhom = new int[NUMBER_CARD_IN_HANDS];
            int index = 0;
            for (int i = 0; i < numberCardRemains; i++) {
                if (!isBelongOfFlushSet[i]) {
                    cardNotPhom[index] = cardInHands[i].getCardId();
                    index++;
                }
            }
            //tim cach add no vao phom
            try {
                addToPhom(cardNotPhom, index, saveId);
            } catch (Exception ex) {
                manager.logError(ex.toString(), ex);
            }
        }
        numberPhoms = markPhom();
        Debug.d("number phom:" + numberPhoms);
        printArr(phomSet, phomIndex);
        if (numberPhoms >= 9) {
            winbyU();
        }
    }
    
    private void winbyU() {
        Debug.d("U thang ca lang");
        int phomSendToServerIndex = 0;
        int[] phomSendToServerId = new int[NUMBER_CARD_IN_HANDS];
        
        for (int i = 0; i < phomIndex[0]; i++) {
            phomSendToServerId[phomSendToServerIndex] = phomSet[0][i];
            phomSendToServerIndex++;
        }
        
        for (int i = 0; i < phomIndex[1]; i++) {
            phomSendToServerId[phomSendToServerIndex] = phomSet[1][i];
            phomSendToServerIndex++;
        }
        
        for (int i = 0; i < phomIndex[2]; i++) {
            phomSendToServerId[phomSendToServerIndex] = phomSet[2][i];
            phomSendToServerIndex++;
        }
        parent.request.haphom(playerId, phomSendToServerId, phomSendToServerIndex);
        movePhomSet(phomSendToServerId, phomSendToServerIndex, playerId);
        parent.request.winUPhom(-1);
    }
    
    private void addToPhom(int[] cardIds, int index, int saveId) {
        Debug.d(gameData.getMyName() + ":add phom");
        printArr2(cardIds, index);
//        Debug.d("card check");
        int phomId = 0;
        int typeSet = 0;
        boolean isAdded = false;
        do {
            int[] set = phomSet[phomId];
            int setIndex = phomIndex[phomId];
            if (set[0] % 13 == set[1] % 13) {
                typeSet = PAIR_SET;
                sortCardIncrease(cardIds, index);
                if (setIndex == 4) {
                    return;
                }
            } else {
                typeSet = FLUSH_SET;
                sortIncreaseBySuit(cardIds, index);
                if (setIndex == 5) {
                    return;
                }
            }
            Debug.d("type set :" + typeSet);
            if (typeSet == PAIR_SET) {
                for (int i = 0; i < index; i++) {
                    int cardId = cardIds[i];
                    if (cardId % 13 == set[0] % 13) {
                        Debug.d("card id :" + cardId);
                        Debug.d("card check id:" + cardCheckIdArr[0]);
                        phomSet[phomId][setIndex] = cardId;
                        phomIndex[phomId] = setIndex + 1;
//                        isAdded = true;
                        break;
                    }
                }
            }
            if (typeSet == FLUSH_SET) {
                int maxId = set[setIndex - 1];
                int minId = set[0];
                // sort
                for (int i = 0; i < index; i++) {
                    int cardId = cardIds[i];
                    if (cardId / 13 == minId / 13) {
                        if (cardId == minId - 2 && i < index - 1) {
                            if (cardIds[i + 1] == minId - 1) {
                                setIndex++;
                                for (int k = setIndex - 1; k >= 1; k--) {
                                    phomSet[phomId][k] = phomSet[phomId][k - 1];
                                }
                                phomSet[phomId][0] = cardId;
                                phomIndex[phomId] = setIndex;
                            }
                        }
                        if (cardId == minId - 1) {
                            setIndex++;
                            for (int k = setIndex - 1; k >= 1; k--) {
                                phomSet[phomId][k] = phomSet[phomId][k - 1];
                            }
                            phomSet[phomId][0] = cardId;
                            phomIndex[phomId] = setIndex;
                        }
                        if (cardId == maxId + 1) {
                            phomSet[phomId][setIndex] = cardId;
                            setIndex++;
                            phomIndex[phomId] = setIndex;
                        }
                        if (cardId == maxId + 2 && i > 0) {
                            if (cardIds[i - 1] == maxId + 1) {
                                phomSet[phomId][setIndex] = cardId;
                                setIndex++;
                                phomIndex[phomId] = setIndex;
                            }
                        }
                    }
                }
            }
            phomId++;
        } while (phomId < saveId);
//        Debug.d("is added :" + isAdded);
//        if (isAdded) {
//            extractPhom();
//        }
    }
    
    private int markPhom() {
        int numberCardInPhom = 0;
        for (int i = 0; i < numberCardRemains; i++) {
            isBelongOfFlushSet[i] = false;
        }
        
        for (int i = 0; i < phomIndex[0]; i++) {
            for (int j = 0; j < numberCardRemains; j++) {
                if (phomSet[0][i] == cardInHands[j].getCardId()) {
                    isBelongOfFlushSet[j] = true;
                    numberCardInPhom++;
                }
            }
        }
        for (int i = 0; i < phomIndex[1]; i++) {
            for (int j = 0; j < numberCardRemains; j++) {
                if (phomSet[1][i] == cardInHands[j].getCardId()) {
                    isBelongOfFlushSet[j] = true;
                    numberCardInPhom++;
                }
            }
        }
        for (int i = 0; i < phomIndex[2]; i++) {
            for (int j = 0; j < numberCardRemains; j++) {
                if (phomSet[2][i] == cardInHands[j].getCardId()) {
                    isBelongOfFlushSet[j] = true;
                    numberCardInPhom++;
                }
            }
        }
        return numberCardInPhom;
    }
    
    private boolean isRepeat(int pIndex, int fIndex) {
        for (int i = 0; i < pairIndex[pIndex]; i++) {
            for (int j = 0; j < flushIndex[fIndex]; j++) {
                if (pairSet[pIndex][i] == flushSet[fIndex][j]) {
                    return true;
                }
            }
        }
        return false;
    }
    
    private int chooseSet(int pId, int fId) {
        int pIndex = pairIndex[pId];
        int fIndex = flushIndex[fId];
        if (pIndex == 3 && fIndex == 3) {
            if (sumPhomPoint(pairSet[pId], pIndex) > sumPhomPoint(flushSet[fId], fIndex)) {
                return CHOOSE_PAIR;
            } else {
                return CHOOSE_FLUSH;
            }
        }
        if (pIndex == 3 && fIndex > 3) {
            if (flushSet[fId][0] % 13 == pairSet[pId][0] % 13) {
                flushSet[fId][0] = -1;
                return CHOOSE_ALL;
            }
            if (flushSet[fId][fIndex - 1] % 13 == pairSet[pId][0] % 13) {
                flushSet[fId][fIndex - 1] = -1;
                return CHOOSE_ALL;
            }
            
            if (sumPhomPoint(pairSet[pId], pIndex) > sumPhomPoint(flushSet[fId], fIndex)) {
                return CHOOSE_PAIR;
            } else {
                return CHOOSE_FLUSH;
            }
        }
        if (pIndex == 4) {
            for (int i = 0; i < pIndex; i++) {
                if (pairSet[pId][i] / 13 == flushSet[fId][0] / 13) {
                    pairSet[pId][i] = -1;
                    return CHOOSE_ALL;
                }
            }
        }
        
        return CHOOSE_ALL;
    }
    
    private int sumPhomPoint(int[] arr, int index) {
        int sum = 0;
        for (int i = 0; i < index; i++) {
            sum += getPoint(arr[i]);
        }
//        Debug.d("sum :"+sum);
        return sum;
    }
    
    private int getPoint(int cardId) {
        return cardId % 13 + 1;
    }
    
    private int choosePhom(int startId) {
        boolean[] chooseType = new boolean[4];
        if (numberFlushs == 1 && numberPairs == 1) {
            if (isRepeat(0, 0)) {
                switch (chooseSet(0, 0)) {
                    case CHOOSE_FLUSH:
                        chooseType[2] = true;
                        break;
                    case CHOOSE_PAIR:
                        chooseType[0] = true;
                        break;
                    case CHOOSE_ALL:
                        chooseType[0] = true;
                        chooseType[2] = true;
                        break;
                }
            } else {
                chooseType[0] = true;
                chooseType[2] = true;
            }
        }
        if (numberPairs == 1 && numberFlushs == 2) {
            int repeatType = 0;
            if (isRepeat(0, 0)) {
                repeatType += 2;
            }
            if (isRepeat(0, 1)) {
                repeatType += 4;
            }
            if (repeatType == 6) {
                chooseType[3] = true;
                chooseType[2] = true;
            }
            if (repeatType == 0) {
                chooseType[3] = true;
                chooseType[2] = true;
                chooseType[0] = true;
            }
            if (repeatType == 2) {
                chooseType[3] = true;
                switch (chooseSet(0, 0)) {
                    case CHOOSE_FLUSH:
                        chooseType[2] = true;
                        break;
                    case CHOOSE_PAIR:
                        chooseType[0] = true;
                        break;
                    case CHOOSE_ALL:
                        chooseType[0] = true;
                        chooseType[2] = true;
                        break;
                }
            }
            if (repeatType == 4) {
                chooseType[2] = true;
                switch (chooseSet(0, 1)) {
                    case CHOOSE_FLUSH:
                        chooseType[3] = true;
                        break;
                    case CHOOSE_PAIR:
                        chooseType[0] = true;
                        break;
                    case CHOOSE_ALL:
                        chooseType[0] = true;
                        chooseType[3] = true;
                        break;
                }
            }
            
            
        }
        if (numberPairs == 2 && numberFlushs == 1) {
            int repeatType = 0;
            if (isRepeat(0, 0)) {
                repeatType += 2;
            }
            if (isRepeat(1, 0)) {
                repeatType += 4;
            }
            if (repeatType == 6) {
                chooseType[0] = true;
                chooseType[1] = true;
            }
            if (repeatType == 0) {
                chooseType[0] = true;
                chooseType[1] = true;
                chooseType[2] = true;
            }
            if (repeatType == 2) {
                chooseType[1] = true;
                switch (chooseSet(0, 0)) {
                    case CHOOSE_FLUSH:
                        chooseType[2] = true;
                        break;
                    case CHOOSE_PAIR:
                        chooseType[0] = true;
                        break;
                    case CHOOSE_ALL:
                        chooseType[0] = true;
                        chooseType[2] = true;
                        break;
                }
            }
            if (repeatType == 4) {
                chooseType[0] = true;
                switch (chooseSet(1, 0)) {
                    case CHOOSE_FLUSH:
                        chooseType[2] = true;
                        break;
                    case CHOOSE_PAIR:
                        chooseType[1] = true;
                        break;
                    case CHOOSE_ALL:
                        chooseType[1] = true;
                        chooseType[3] = true;
                        break;
                }
            }
            
        }
        int phomId = startId;
        int index = 0;
        if (chooseType[0]) {
            Debug.d("choose 0");
            for (int i = 0; i < pairIndex[0]; i++) {
                if (pairSet[0][i] != -1) {
                    phomSet[phomId][index] = pairSet[0][i];
                    index++;
                    phomIndex[phomId] = index;
                }
            }
            phomId++;
            
        }
        if (chooseType[1]) {
            index = 0;
            Debug.d("choose 1");
            for (int i = 0; i < pairIndex[1]; i++) {
                if (pairSet[1][i] != -1) {
                    phomSet[phomId][index] = pairSet[1][i];
                    index++;
                    phomIndex[phomId] = index;
                }
            }
            phomId++;
            
        }
        if (chooseType[2]) {
            index = 0;
            Debug.d("choose 2");
            for (int i = 0; i < flushIndex[0]; i++) {
                if (flushSet[0][i] != -1) {
                    phomSet[phomId][index] = flushSet[0][i];
                    index++;
                    phomIndex[phomId] = index;
                }
            }
            phomId++;
            
        }
        if (chooseType[3]) {
            index = 0;
            Debug.d("choose 3");
            for (int i = 0; i < flushIndex[1]; i++) {
                if (flushSet[1][i] != -1) {
                    phomSet[phomId][index] = flushSet[1][i];
                    index++;
                    phomIndex[phomId] = index;
                }
            }
            phomId++;
            
        }
        return (phomId + startId);
        
    }
    
    private int extractFlush(int[] cardCheck, int arrLength) {
//        Debug.d("extrac flush");
        sortCardDecreaseBySuit(cardCheck, arrLength);
        flushSet = new int[3][5];
        flushIndex = new int[3];
        for (int i = 0; i < 3; i++) {
            flushSet[i] = new int[5];
        }
//        printArr2(cardCheck, arrLength);
        int index = 0;
        for (int i = 0; i < arrLength - 2; i++) {
            if (cardCheck[i] == cardCheck[i + 1] - 1
                    && cardCheck[i + 1] == cardCheck[i + 2] - 1
                    && cardCheck[i] / 13 == cardCheck[i + 1] / 13
                    && cardCheck[i] / 13 == cardCheck[i + 2] / 13) {
                flushSet[index][0] = cardCheck[i];
                flushSet[index][1] = cardCheck[i + 1];
                flushSet[index][2] = cardCheck[i + 2];
                int countNumberCard = 3;
                
                if (i < arrLength - 3) {
                    if (cardCheck[i + 2] == cardCheck[i + 3] - 1
                            && cardCheck[i] / 13 == cardCheck[i + 3] / 13) {
                        flushSet[index][countNumberCard] = cardCheck[i + 3];
                        countNumberCard++;
                    }
                }
                if (i < arrLength - 4 && countNumberCard == 4) {
                    if (cardCheck[i + 3] == cardCheck[i + 4] - 1
                            && cardCheck[i] / 13 == cardCheck[i + 4] / 13) {
                        flushSet[index][countNumberCard] = cardCheck[i + 4];
                        countNumberCard++;
                    }
                }
                if (i < arrLength - 5 && countNumberCard == 5) {
                    if (cardCheck[i + 4] == cardCheck[i + 5] - 1
                            && cardCheck[i] / 13 == cardCheck[i + 5] / 13) {
                        countNumberCard = 3;
                    }
                }
                flushIndex[index] = countNumberCard;
                i += countNumberCard - 1;
                index++;
                // Debug.d("next i :" + i);
            }
        }
//        printArr(flushSet, flushIndex);
        return index;
    }
    
    private int extracPair(int[] cardCheck, int arrLength) {
//        Debug.d("extract pair");
        pairSet = new int[3][4];
        pairIndex = new int[3];
        for (int i = 0; i < 3; i++) {
            pairSet[i] = new int[4];
        }
        // xep theo do giam cua quan bai
        sortCardIncrease(cardCheck, arrLength);
//        printArr2(cardCheck, arrLength);
        int index = 0;
        for (int i = 0; i < arrLength - 2; i++) {
            if (cardCheck[i] % 13 == cardCheck[i + 1] % 13
                    && cardCheck[i + 1] % 13 == cardCheck[i + 2] % 13) {
                int countNumberCard = 0;
                pairSet[index][countNumberCard] = cardCheck[i];
                pairSet[index][countNumberCard + 1] = cardCheck[i + 1];
                pairSet[index][countNumberCard + 2] = cardCheck[i + 2];
                countNumberCard += 3;
                if (i < arrLength - 3) {
                    if (cardCheck[i + 2] % 13 == cardCheck[i + 3] % 13) {
                        pairSet[index][countNumberCard] = cardCheck[i + 3];
                        countNumberCard++;
                    }
                }
                pairIndex[index] = countNumberCard;
                i += countNumberCard - 1;
                index++;
            }
        }
//        printArr(pairSet, pairIndex);
        return index;
    }
    
    private void sortCardDecreaseBySuit(int[] cardIds, int arrLength) {
        for (int i = 0, l = arrLength; i < l - 1; i++) {
            for (int j = i; j < l; j++) {
                if (cardIds[j] < cardIds[i]) {
                    int tg = cardIds[i];
                    cardIds[i] = cardIds[j];
                    cardIds[j] = tg;
                }
            }
        }
        
    }
    
    public void sortCardIncrease(int[] dataArr, int arrLength) {
        for (int i = 0, l = arrLength; i < l - 1; i++) {
            for (int j = i; j < l; j++) {
                if ((dataArr[i]) % 13 > (dataArr[j]) % 13) {
                    int tg = dataArr[i];
                    dataArr[i] = dataArr[j];
                    dataArr[j] = tg;
                } else if (dataArr[i] % 13 == dataArr[j] % 13) {
                    if (dataArr[i] / 13 > dataArr[j] / 13) {
                        int tg = dataArr[i];
                        dataArr[i] = dataArr[j];
                        dataArr[j] = tg;
                    }
                }
            }
        }
        
    }
    
    private void printArr(int[][] arr, int[] arrIndex) {
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < arrIndex[i]; j++) {
                Debug.d("set :" + arr[i][j]);
            }
        }
    }
//-----------------------------------------------------------------------------

    @Override
    public void doLoop() {
        super.doLoop();
    }
    
    @Override
    void doFightCard() {
        if (!isJoined && isViewer && !isWaitingJoinResult) {
            parent.request.joinGame(gameData.myName);
            isWaitingJoinResult = true;
        }
        if (!isBeginGame && playerId == firtTurn) {
            return;
        }
        if (isFinishGame) {
            if (!isViewer) {
                for (int i = 0; i < numberPlayers; i++) {
                    gameData.readyStates[i] = 0;
                }
                if (playerWinByUId == -1) {
                    parent.request.finishPhom(playeIdWin);
                } else {
                    parent.request.finishPhom(playerWinByUId);
                }
                parent.changeProcesser(RoBot.WAITING);
            }
            return;
        }
        
        if (isWaitFinish) {
            return;
        }
        
        if (gameTurn == playerId && !isViewer) {
            if (isGetMoreCard) {
                getMoreCard();
                return;
            }
            if (isHaPhom) {
                isHaPhom = false;
                doHaPhom();
                Debug.d("ha phom");
                return;
            }
            //cho boc dc bai da
            if (isStartFight) {
                isStartFight = false;
                sortCardBySet();
                fightChooseCard(cardChooseIndex);
            }
        }
    }
    
    private void addCardToFightedList(Card cardToAdd, int id) {
        int posId = ((id - playerId + maxPlayer) % maxPlayer);
//        Debug.d("post id:" + posId);
//        Debug.d("card index :" + cardToAdd.getCardId());
        switch (posId) {
            case 0:
                cardFighted[posId][cardFightedIndex[posId]] = cardToAdd;
                cardFightedIndex[posId] += 1;
                break;
            case 1:
                cardFighted[posId][cardFightedIndex[posId]] = cardToAdd;
                cardFightedIndex[posId] += 1;
                
                break;
            case 2:
                cardFighted[posId][cardFightedIndex[posId]] = cardToAdd;
                cardFightedIndex[posId] += 1;
                break;
            case 3:
                cardFighted[posId][cardFightedIndex[posId]] = cardToAdd;
                cardFightedIndex[posId] += 1;
                break;
        }
        Debug.d("add to fighted  :" + cardFightedIndex[posId] + "," + id);
        
    }
    
    private void removeCardInHand(int cardChooseIndex) {
        for (int i = cardChooseIndex; i < numberCardRemains - 1; i++) {
            cardInHands[i] = cardInHands[i + 1];
        }
        cardInHands[numberCardRemains - 1] = null;
        numberCardRemains--;
        Debug.d("remove from hand:" + numberCardRemains);
    }
    
    private void movePhomSet(int[] phomSet, int phomSetLength, int id) {
        int index = 0;
        int posId = ((id - playerId + maxPlayer) % maxPlayer);
        int startIndex = phomCardIndex[posId];
        switch (posId) {
            case 0:
                if (!isViewer) {
                    for (int i = 0; i < phomSetLength; i++) {
                        for (int j = 0; j < numberCardRemains; j++) {
                            if (phomSet[i] == cardInHands[j].getCardId()) {
                                Card card = cardInHands[j];
                                index = phomCardIndex[0];
                                cardPhomSet[0][index] = card;
                                index += 1;
                                phomCardIndex[0] = index;
                                for (int k = j; k < numberCardRemains - 1; k++) {
                                    cardInHands[k] = cardInHands[k + 1];
                                }
                                cardInHands[numberCardRemains - 1] = null;
                                numberCardRemains--;
                            }
                        }
                    }
                    index = phomCardIndex[0];
                    cardEatedIndex0 = 0;
                } else {
                    phomCardIndex[posId] += phomSetLength;
                    cardEatedIndex0 = 0;
                }
                break;
            case 1:
                for (int i = startIndex; i < phomSetLength + startIndex; i++) {
                    phomCardIndex[posId]++;
                }
                cardEatedIndex1 = 0;
                break;
            case 2:
                
                for (int i = startIndex; i < phomSetLength + startIndex; i++) {
                    phomCardIndex[posId]++;
                }
                cardEatedIndex2 = 0;
                break;
            case 3:
                for (int i = startIndex; i < phomSetLength + startIndex; i++) {
                    phomCardIndex[posId]++;
                }
                cardEatedIndex3 = 0;
                break;
        }
        
    }
    
    private void fightChooseCard(int cardChooseIndex) {
        parent.request.fightCardPhom(playerId, cardInHands[cardChooseIndex].getCardId());
        playerFightid = playerId;
        cardCanbeEated = cardInHands[cardChooseIndex];
        addCardToFightedList(cardCanbeEated, playerId);
        removeCardInHand(cardChooseIndex);
        //check xem da danh den con cuoi chua
        Debug.d("number card figth :" + cardFightedIndex[0]);
        if (cardFightedIndex[0] == 4) {
            isWaitFinish = true;
            int cardRemainIndex = 0;
            int[] cardRemainIds = new int[NUMBER_CARD_IN_HANDS];
            for (int i = 0; i < numberCardRemains; i++) {
                cardRemainIds[cardRemainIndex] = cardInHands[i].getCardId();
                cardRemainIndex++;
            }
            parent.request.finishPhom(cardRemainIds, cardRemainIndex);
            int numberPlayerFinish = countPlayerFinish();
            //thang danh cuoi cung
            Debug.d("number finish :" + numberPlayerFinish);
            if (numberPlayerFinish == numberPlayers) {
                parent.request.fnMessgePhom();
                isFinishGame = true;
            }
        }
        extractPhom();
        if (!isFinishGame) {
            nextGameTurn();
        }
    }
    
    private int countPlayerFinish() {
        int numberFinish = 0;
        for (int i = 0; i < maxPlayer; i++) {
            if (gameData.isPlays[i]) {
                int posId = getPosId(i);
                if (cardFightedIndex[posId] == 4) {
                    numberFinish++;
                }
            }
        }
        return numberFinish;
    }
    
    private int getPosId(int id) {
        return ((id - playerId + maxPlayer) % maxPlayer);
    }
    
    private void nextGameTurn() {

//        Debug.d("pre turn  :" + gameTurn);
        int preTurn = gameTurn;
        for (int i = preTurn + 1; i < maxPlayer + preTurn; i++) {
            if (gameData.isPlays[i % maxPlayer]) {
                gameTurn = i % maxPlayer;
                break;
            }
        }
        Debug.d("game turn :" + gameTurn);
        isGetMoreCard = true;
    }
    
    private void doHaPhom() {
        extractPhom();
        if (numberPhoms > 0) {
            int phomSendToServerIndex = 0;
            int[] phomSendToServerId = new int[NUMBER_CARD_IN_HANDS];
            
            for (int i = 0; i < phomIndex[0]; i++) {
                phomSendToServerId[phomSendToServerIndex] = phomSet[0][i];
                phomSendToServerIndex++;
            }
            
            for (int i = 0; i < phomIndex[1]; i++) {
                phomSendToServerId[phomSendToServerIndex] = phomSet[1][i];
                phomSendToServerIndex++;
            }
            
            for (int i = 0; i < phomIndex[2]; i++) {
                phomSendToServerId[phomSendToServerIndex] = phomSet[2][i];
                phomSendToServerIndex++;
            }
            parent.request.haphom(playerId, phomSendToServerId, phomSendToServerIndex);
            movePhomSet(phomSendToServerId, phomSendToServerIndex, playerId);
        }
    }
    
    private void getMoreCard() {
        if (cardCanbeEated != null) {
            if (checkAutoEatCard(cardCanbeEated.getCardId())) {
                int eatType = getEatType();
                parent.request.eatCardPhom(playerFightid, cardCanbeEated.getCardId(), eatType);
                playerEatId = playerId;
                isEatCard = true;
                isGetMoreCard = false;
                addEatedCardToList();
                if (playerFightid != firstHaPhom) {
                    changeFirstHaPhom();
                }
                firstHaPhom = (++firstHaPhom) % numberPlayers;
                isStartFight = false;
                checkHaphom();
            } else {
                //boc bai
                parent.request.getCardDraw();
                isGetMoreCard = false;
            }
        } else {
            parent.request.getCardDraw();
            isGetMoreCard = false;
        }
        
    }
    
    private void changeFirstHaPhom() {
//        Debug.d("chuyen ha phom dau:" + firstHaPhom);
//        Debug.d("thang an :" + gameTurn);""
//        Debug.d("thang bi an :" + playerFightid);
        for (int i = playerEatId; i < playerEatId + maxPlayer; i++) {
            Debug.d("i :" + i);
            Debug.d("fight :" + cardFightedIndex[getPosId(playerFightid)] + "," + i);
            Debug.d("transfer:" + cardFightedIndex[getPosId(i % maxPlayer)] + "," + i);
            if (cardFightedIndex[getPosId(i % maxPlayer)] > cardFightedIndex[getPosId(playerFightid)]) {
                Card cardTransfer = removeCardFromFightedList(i % maxPlayer);
                addCardToFightedList(cardTransfer, playerFightid);
                break;
            }
        }
    }
    
    private Card removeCardFromFightedList(int id) {
        int posId = (id - playerId + maxPlayer) % maxPlayer;
        int index = cardFightedIndex[posId];
        Debug.d("index remove :" + index);
        Debug.d("posId :" + posId);
        Card cardRemove = cardFighted[posId][index - 1];
        Debug.d("card id remove :" + cardRemove.getCardId());
        
        switch (posId) {
            case 0:
                cardFighted[0][index - 1] = null;
                cardFightedIndex[0]--;
                break;
            case 1:
                cardFighted[1][index - 1] = null;
                cardFightedIndex[1]--;
                break;
            case 2:
                cardFighted[2][index - 1] = null;
                cardFightedIndex[2]--;
                
                break;
            case 3:
                cardFighted[3][index - 1] = null;
                cardFightedIndex[3]--;
                
                break;
        }
        Debug.d("remove card fighted index  :" + cardFightedIndex[posId] + "," + id);
        if (posId == 0 && cardFightedIndex[posId] == 3) {
            isWaitFinish = false;
        }
        return cardRemove;
    }
    
    private void checkHaphom() {
        if (gameTurn == playerId) {
            if (cardFightedIndex[0] == 3) {
                isHaPhom = true;
                setTimeWait(15000);
            } else {
                isHaPhom = false;
            }
            Debug.d("check ha phom :" + isHaPhom);
            
        }
    }
    
    private void addEatedCardToList() {
        if (gameTurn == playerId && !isViewer) {
            cardInHands[numberCardRemains] = cardCanbeEated;
            numberCardRemains++;
            cardCanbeEated = null;
            isEatCard = false;
            Debug.d("eat from player id :" + playerFightid);
            removeCardFromFightedList(playerFightid);
            numberEats++;
            //danh dau quan da xep vao phom
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < numberCardRemains; j++) {
                    if (cardInHands[j].getCardId() == cardCheckIdArr[i]) {
                        Debug.d("card eat :" + cardCheckIdArr[i]);
                        cardInHands[j].isCardEated = true;
                        cardInHands[j].eatId = (numberEats - 1);
                        cardInHands[j].phomId = i;
                    }
                }
            }
            
            sortCardBySet();
            extractPhom();
        } else {
            int posId = ((playerEatId - playerId + maxPlayer) % maxPlayer);
            switch (posId) {
                case 1:
                    cardEated1[cardEatedIndex1] = cardCanbeEated;
                    cardEatedIndex1++;
                    break;
                case 2:
                    cardEated2[cardEatedIndex2] = cardCanbeEated;
                    cardEatedIndex2++;
                    
                    break;
                case 3:
                    cardEated3[cardEatedIndex3] = cardCanbeEated;
                    cardEatedIndex3++;
                    
                    break;
            }
            cardCanbeEated = null;
            isEatCard = false;
            removeCardFromFightedList(playerFightid);
        }
    }
    
    public void swapCard(int srcIndex, int desIndex) {
        // Debug.d("swap card");
        if (srcIndex < 0) {
            srcIndex = numberCardRemains - 1;
        } else if (srcIndex == numberCardRemains) {
            srcIndex = 0;
        }
        if (desIndex < 0) {
            desIndex = numberCardRemains - 1;
        } else if (desIndex == numberCardRemains) {
            desIndex = 0;
        }
        Card tg = cardInHands[srcIndex];
        cardInHands[srcIndex] = cardInHands[desIndex];
        cardInHands[desIndex] = tg;
        
    }
    
    private void sortCardBySet() {
        extractPhom();
        // xep phom
        int startIndex = 0;
        for (int i = 0; i < phomIndex[0]; i++) {
            for (int j = startIndex; j < numberCardRemains; j++) {
                if (cardInHands[j].getCardId() == phomSet[0][i]) {
                    swapCard(startIndex, j);
                    startIndex++;
                }
            }
        }
        for (int i = 0; i < phomIndex[1]; i++) {
            for (int j = startIndex; j < numberCardRemains; j++) {
                if (cardInHands[j].getCardId() == phomSet[1][i]) {
                    swapCard(startIndex, j);
                    startIndex++;
                }
            }
        }
        for (int i = 0; i < phomIndex[2]; i++) {
            for (int j = startIndex; j < numberCardRemains; j++) {
                if (cardInHands[j].getCardId() == phomSet[2][i]) {
                    swapCard(startIndex, j);
                    startIndex++;
                }
            }
        }

        //xep cac con ko thuoc phom
        cardChooseIndex = startIndex;
        for (int i = startIndex; i < numberCardRemains - 1; i++) {
            for (int j = i; j < numberCardRemains; j++) {
                if (cardInHands[i].getCardId() % 13 < cardInHands[j].getCardId() % 13) {
                    swapCard(i, j);
                } else if (cardInHands[i].getCardId() % 13 == cardInHands[j].getCardId() % 13) {
                    if (cardInHands[i].getCardId() / 13 < cardInHands[j].getCardId() / 13) {
                        swapCard(i, j);
                    }
                }
            }
        }
    }
    
    private int getEatType() {
        if (cardFightedIndex[getPosId(playerFightid)] == 4) {
            return 2;
        }
        int count = 0;
        for (int i = 0; i < maxPlayer; i++) {
            if (gameData.isPlays[i] && cardFightedIndex[i] == 3) {
                count++;
            }
        }
        if (count == numberPlayers) {
            return 2;
        }
        return 1;
    }
    
    private boolean checkAutoEatCard(int cardCheckEat) {
        int checkIndex = 0;
        int[] pair = new int[4];
        int[] flush = new int[NUMBER_CARD_IN_HANDS];
        int pairLength = 0;
        int flushLength = 0;
        for (int i = 0; i < numberCardRemains; i++) {
            Card card = cardInHands[i];
            if (!card.isCardEated) {
                cardCheckIdArr[checkIndex] = cardInHands[i].getCardId();
                checkIndex++;
            }
        }
        
        pairLength = findPair(cardCheckIdArr, checkIndex, cardCheckEat, pair);
        flushLength = findFlush(cardCheckIdArr, checkIndex, cardCheckEat, flush);
        Debug.d("check pair :" + pairLength);
        Debug.d("check flush :" + flushLength);
        if (pairLength < 3 && flushLength < 3) {
            return false;
        }
        
        if (pairLength >= 3 && flushLength < 3) {
            cardCheckIdArr[0] = pair[0];
            cardCheckIdArr[1] = pair[1];
            cardCheckIdArr[2] = pair[2];
            return true;
        }
        
        if (flushLength >= 3 && pairLength < 3) {
            Debug.d("check :" + cardCheckEat);
            Debug.d("2:" + flush[0]);
            cardCheckIdArr[0] = flush[0];
            cardCheckIdArr[1] = flush[1];
            cardCheckIdArr[2] = flush[2];
            return true;
        }
        if (flushLength >= 3 && pairLength >= 3) {
            if (sumPhomPoint(pair, pairLength) < sumPhomPoint(flush, flushLength)) {
                cardCheckIdArr[0] = flush[0];
                cardCheckIdArr[1] = flush[1];
                cardCheckIdArr[2] = flush[2];
                return true;
            }
            cardCheckIdArr[0] = pair[0];
            cardCheckIdArr[1] = pair[1];
            cardCheckIdArr[2] = pair[2];
            return true;
        }
        return false;
    }

//-----------------------------------------------------------------------------
    private void processBcMessage(int cardDrawId) {
        Card card = new Card(cardDrawId);
        cardInHands[numberCardRemains] = card;
        numberCardRemains++;
        Debug.d("number card remain :" + numberCardRemains);
        extractPhom();
        checkHaphom();
    }
    
    private void processEaMessage() {
        isEatCard = true;
        playerEatId = gameTurn;
        addEatedCardToList();
        changeFirstHaPhom();
        firstHaPhom = (++firstHaPhom) % numberPlayers;
    }
    
    @Override
    public void processMesage(String[] part) {
        super.processMesage(part);
        Debug.d("phom process :" + part[0]);
        if (part[0].equals("BC")) {
            try {
                isBeginGame = true;
                isStartFight = true;
                int cardDrawId = Integer.parseInt(part[1]);
                processBcMessage(cardDrawId);
                return;
            } catch (Exception ex) {
            }
        }
        if (part[0].equals("DB")) {
            playerFightid = Integer.parseInt(part[1]);
            Debug.d("player fight id :" + playerFightid);
            if (isViewer) {
                gameTurn = playerFightid;
            }
            if (playerFightid != playerId || isViewer) {
                int cardFightId = Integer.parseInt(part[2]);
                cardCanbeEated = new Card(cardFightId);
                addCardToFightedList(cardCanbeEated, playerFightid);
                nextGameTurn();
            }
        }
        if (part[0].equals("EA")) {
            playerFightid = Integer.parseInt(part[1]);
            if (gameTurn == playerId) {
                isStartFight = true;
                return;
            }
            if (gameTurn != playerId || isViewer) {
                processEaMessage();
                return;
            }
            
        }
        if (part[0].equals("FN")) {
            try {
                int playerFinishId = Integer.parseInt(part[1]);
                int result = Integer.parseInt(part[2]);
                resultOrder[playerFinishId] = result;
                Debug.d("id :" + playerFinishId + ",result :" + result);
                if (result == 0) {
                    playeIdWin = playerFinishId;
                }
                
                countFnReceive++;
                if (countFnReceive == numberPlayers) {
                    isFinishGame = true;
                }
                Debug.d("is finish game :" + isFinishGame);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            return;
        }
        if (part[0].equals("U")) {
            playerWinByUId = Integer.parseInt(part[1]);
            Debug.d("player u :" + playerWinByUId);
            
            isFinishGame = true;
            return;
        }
        if (part[0].equals("HP")) {
            int playerHaPhomId = Integer.parseInt(part[1]);
            if (playerId != playerHaPhomId || isViewer) {
                int phomLength = part.length - 2;
                int[] cardReceiveId = new int[phomLength];
                for (int i = 0; i < phomLength; i++) {
                    cardReceiveId[i] = Integer.parseInt(part[i + 2]);
                    Debug.d("card ha phom :" + cardReceiveId[i]);
                }
                movePhomSet(cardReceiveId, phomLength, playerHaPhomId);
            }
            return;
            
        }
        if (part[0].equals("DL")) {
            playerDenLang = Integer.parseInt(part[2]);
            playerWinByUId = Integer.parseInt(part[1]);
            Debug.d("player u :" + playerWinByUId);
            isFinishGame = true;
            return;
        }
        
        if (part[0].equals("RO")) {
            gameData.setRoArrData(part);
            if (numberPlayers == 1) {
                isFinishGame = true;
            }
            if (!gameData.isPlays[gameTurn]) {
                nextGameTurn();
            }
            return;
        }
        if (part[0].equals("JS")) {
            int joinResult = Integer.parseInt(part[1]);
            if (joinResult == 0) {
                isJoined = false;
                parent.request.exitTable();
            } else {
                isJoined = true;
            }
            return;
        }
        if (part[0].equals("SE")) {
            gameData.setNumberPlayerInTable(part);
            parent.changeProcesser(RoBot.TABLE_CHOOSER);
            return;
        }
        if (part[0].equals("INFO")) {
            gameData.setInfoData(part);
            return;
        }
        if (part[0].equals("RE")) {
            gameData.setReArrData(part);
            if (!isViewer && isJoined) {
                parent.changeProcesser(RoBot.WAITING);
            }
            return;
        }
        if (part[0].equals("CM")) {
            try {
                int money = Integer.parseInt(part[2]);
                int id = Integer.parseInt(part[1]);
                gameData.changeMoney(id, money);
            } catch (Exception ex) {
                StringBuilder buffer = new StringBuilder();
                for (int i = 0; i < part.length; i++) {
                    buffer.append(part[i]).append("|");
                }
                ex.printStackTrace();
                manager.logUserStatus(ex.toString() + buffer.toString(), LogDef.LOG_LEVEL.LOG_ERROR);
                
            }
            return;
        }
        
    }
}
